﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Net;
using System.IO;
using System.Data.OleDb;
using TheOutLetLibrary.Infraestrutura;
using System.Threading;
using System.Globalization;

namespace TheOutLetLibrary.Dominio {

    public class Carregadork_order {

        private IFactoryDAO factoryDAO;
        private k_order order;

        public Carregadork_order(IFactoryDAO factoryDAO) {
            this.factoryDAO = factoryDAO;
        }

        public k_orderLog CarregueOrder(int orderID) {

            string statusDaCarga = "Carga efetuada com sucesso";
            order = new k_order();

            Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
            Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");

            try {

                XElement orderXml = APIKanlo.CarregaXml("order/" + orderID.ToString());
                XNamespace ad = "http://kanlo.com.br/order";

                // tabela k_order
                order.NR_PEDIDO = Int32.Parse(orderXml.Element(ad + "id").Value);
                order.DateCreated = DateTime.Parse(orderXml.Element(ad + "dateCreated").Value);
                order.LastUpdated = DateTime.Parse(orderXml.Element(ad + "lastUpdated").Value);
                order.Status = orderXml.Element(ad + "status").Value;

                // tabela k_customer
                order.customer.NR_PEDIDO = Int32.Parse(orderXml.Element(ad + "id").Value);
                order.customer.birthdate = DateTime.Parse(orderXml.Element(ad + "customer").Element(ad + "birthdate").Value);
                order.customer.comment = orderXml.Element(ad + "customer").Element(ad + "comment").Value;
                order.customer.Id = Int32.Parse(orderXml.Element(ad + "customer").Element(ad + "id").Value);
                order.customer.document = orderXml.Element(ad + "customer").Element(ad + "document").Value;
                order.customer.email = orderXml.Element(ad + "customer").Element(ad + "email").Value;
                order.customer.gender = orderXml.Element(ad + "customer").Element(ad + "gender").Value;
                order.customer.isPhysicalPerson = bool.Parse(orderXml.Element(ad + "customer").Element(ad + "isPhysicalPerson").Value);
                order.customer.name = orderXml.Element(ad + "customer").Element(ad + "name").Value;
                order.customer.nickName = orderXml.Element(ad + "customer").Element(ad + "nickName").Value;

                // tabela k_phone
                if(orderXml.Element(ad + "customer").Element(ad + "phone") != null) {
                    order.customer.phone = new k_phone();
                    order.customer.phone.ddd = orderXml.Element(ad + "customer").Element(ad + "phone").Element(ad + "ddd").Value;
                    order.customer.phone.number = orderXml.Element(ad + "customer").Element(ad + "phone").Element(ad + "number").Value;
                    order.customer.phone.NR_PEDIDO = order.NR_PEDIDO;
                }
          
                // tabela k_cellphone
                if(orderXml.Element(ad + "customer").Element(ad + "cellphone") != null) {
                    order.customer.cellphone = new k_phone();
                    order.customer.cellphone.ddd = orderXml.Element(ad + "customer").Element(ad + "cellphone").Element(ad + "ddd").Value;
                    order.customer.cellphone.number = orderXml.Element(ad + "customer").Element(ad + "cellphone").Element(ad + "number").Value;
                    order.customer.cellphone.NR_PEDIDO = order.NR_PEDIDO;
                }

                // tabela k_shipping
                if(orderXml.Element(ad + "addresses").Element(ad + "shipping") != null) {
                    order.AddressShipping = new k_address();
                    order.AddressShipping.id = orderXml.Element(ad + "addresses").Element(ad + "shipping").Element(ad + "id").Value;
                    order.AddressShipping.address = orderXml.Element(ad + "addresses").Element(ad + "shipping").Element(ad + "address").Value;
                    order.AddressShipping.addressName = orderXml.Element(ad + "addresses").Element(ad + "shipping").Element(ad + "addressName").Value;
                    order.AddressShipping.city = orderXml.Element(ad + "addresses").Element(ad + "shipping").Element(ad + "city").Value;
                    order.AddressShipping.contactName = orderXml.Element(ad + "addresses").Element(ad + "shipping").Element(ad + "contactName").Value;
                    order.AddressShipping.number = orderXml.Element(ad + "addresses").Element(ad + "shipping").Element(ad + "number").Value;
                    order.AddressShipping.province = orderXml.Element(ad + "addresses").Element(ad + "shipping").Element(ad + "province").Value;
                    if(orderXml.Element(ad + "addresses").Element(ad + "shipping").Element(ad + "complement") != null) {
                        order.AddressShipping.complement = orderXml.Element(ad + "addresses").Element(ad + "shipping").Element(ad + "complement").Value;
                    }
                    if(orderXml.Element(ad + "addresses").Element(ad + "shipping").Element(ad + "reference") != null) {
                        order.AddressShipping.reference = orderXml.Element(ad + "addresses").Element(ad + "shipping").Element(ad + "reference").Value;
                    }
                    order.AddressShipping.state = orderXml.Element(ad + "addresses").Element(ad + "shipping").Element(ad + "state").Value;
                    order.AddressShipping.zipcode = orderXml.Element(ad + "addresses").Element(ad + "shipping").Element(ad + "zipcode").Value;
                    order.AddressShipping.NR_PEDIDO = order.NR_PEDIDO;
                }

                // tabela k_billing
                if(orderXml.Element(ad + "addresses").Element(ad + "billing") != null) {
                    order.AddressBilling = new k_address();
                    order.AddressBilling.id = orderXml.Element(ad + "addresses").Element(ad + "billing").Element(ad + "id").Value;
                    order.AddressBilling.address = orderXml.Element(ad + "addresses").Element(ad + "billing").Element(ad + "address").Value;
                    order.AddressBilling.addressName = orderXml.Element(ad + "addresses").Element(ad + "billing").Element(ad + "addressName").Value;
                    order.AddressBilling.city = orderXml.Element(ad + "addresses").Element(ad + "billing").Element(ad + "city").Value;
                    order.AddressBilling.contactName = orderXml.Element(ad + "addresses").Element(ad + "billing").Element(ad + "contactName").Value;
                    order.AddressBilling.number = orderXml.Element(ad + "addresses").Element(ad + "billing").Element(ad + "number").Value;
                    order.AddressBilling.province = orderXml.Element(ad + "addresses").Element(ad + "billing").Element(ad + "province").Value;
                    if(orderXml.Element(ad + "addresses").Element(ad + "billing").Element(ad + "complement") != null) {
                        order.AddressBilling.complement = orderXml.Element(ad + "addresses").Element(ad + "billing").Element(ad + "complement").Value;
                    }
                    if(orderXml.Element(ad + "addresses").Element(ad + "billing").Element(ad + "reference") != null) {
                        order.AddressBilling.reference = orderXml.Element(ad + "addresses").Element(ad + "billing").Element(ad + "reference").Value;
                    }
                    order.AddressBilling.state = orderXml.Element(ad + "addresses").Element(ad + "billing").Element(ad + "state").Value;
                    order.AddressBilling.zipcode = orderXml.Element(ad + "addresses").Element(ad + "billing").Element(ad + "zipcode").Value;
                    order.AddressBilling.NR_PEDIDO = order.NR_PEDIDO;
                }

                // tabela k_payment
                order.payment.NR_PEDIDO = order.NR_PEDIDO;
                order.payment.type = orderXml.Element(ad + "payment").Element(ad + "type").Value;
                order.payment.gateway = orderXml.Element(ad + "payment").Element(ad + "gateway").Value;
                order.payment.token = orderXml.Element(ad + "payment").Element(ad + "token").Value;
                order.payment.creditCardbrand = orderXml.Element(ad + "payment").Element(ad + "creditCard").Element(ad + "brand").Value;
                order.payment.creditCardparcels = Int32.Parse(orderXml.Element(ad + "payment").Element(ad + "creditCard").Element(ad + "parcels").Value);

                // tabela k_delivery
                IEnumerable<XElement> deliveries = from delivery in orderXml.Descendants(ad + "deliveries").Descendants(ad + "delivery")
                                                   select delivery;

                foreach(XElement item in deliveries) {
                    k_delivery delivery = new k_delivery();
                    delivery.NR_PEDIDO = order.NR_PEDIDO;
                    delivery.deliveryType = item.Element(ad + "deliveryType").Value;
                    delivery.estimate = DateTime.Parse(item.Element(ad + "estimate").Value);
                    delivery.price = Decimal.Parse(item.Element(ad + "price").Value);
                    delivery.trackingCode = item.Element(ad + "trackingCode").Value;
                    order.deliveries.Add(delivery);
                }

                // tabela k_freight
                order.cart.freight.NR_PEDIDO = order.NR_PEDIDO;
                order.cart.freight.time = Int32.Parse(orderXml.Element(ad + "cart").Element(ad + "freight").Element(ad + "time").Value);
                order.cart.freight.amount = Decimal.Parse(orderXml.Element(ad + "cart").Element(ad + "freight").Element(ad + "amount").Value);
                order.cart.freight.discount = Decimal.Parse(orderXml.Element(ad + "cart").Element(ad + "freight").Element(ad + "discount").Value);
                order.cart.freight.totalAmount = Decimal.Parse(orderXml.Element(ad + "cart").Element(ad + "freight").Element(ad + "totalAmount").Value);


                // tabela k_orderLine
                IEnumerable<XElement> lines = from orderLine in orderXml.Descendants(ad + "cart").Descendants(ad + "orderLines").Descendants(ad + "orderLine")
                                              select orderLine;
                foreach(XElement line in lines) {
                    k_orderLine linha = new k_orderLine();
                    linha.NR_PEDIDO = order.NR_PEDIDO;
                    linha.name = line.Element(ad + "name").Value;
                    linha.variation = line.Element(ad + "variation").Value;
                    linha.skuId = Int32.Parse(line.Element(ad + "skuId").Value);
                    linha.productId = line.Element(ad + "productId").Value;
                    linha.quantity = Int32.Parse(line.Element(ad + "quantity").Value);
                    linha.isKit = bool.Parse(line.Element(ad + "isKit").Value);
                    linha.listPrice = decimal.Parse(line.Element(ad + "listPrice").Value);
                    linha.salePrice = decimal.Parse(line.Element(ad + "salePrice").Value);
                    linha.discount = decimal.Parse(line.Element(ad + "discount").Value);
                    linha.totalAmount = decimal.Parse(line.Element(ad + "totalAmount").Value);
                    order.cart.orderLines.Add(linha);
                }

                // tabele k_cart
                order.cart.NR_PEDIDO = order.NR_PEDIDO;
                order.cart.totalAmount = Decimal.Parse(orderXml.Element(ad + "cart").Element(ad + "totalAmount").Value);
                order.cart.totalDiscountAmount = Decimal.Parse(orderXml.Element(ad + "cart").Element(ad + "totalDiscountAmount").Value);
                order.cart.totalInterestAmount = Decimal.Parse(orderXml.Element(ad + "cart").Element(ad + "totalInterestAmount").Value);

                SalveContextoOrder();

            } catch (Exception ex) {
                statusDaCarga = ex.Message;
            }

            Thread.CurrentThread.CurrentCulture = new CultureInfo("pt-BR");
            Thread.CurrentThread.CurrentUICulture = new CultureInfo("pt-BR");

            return new k_orderLog {
                Order = order,
                StatusDaCarga = statusDaCarga
            };

        }

        public List<int> CarregueListaDeOrders(DateTime dataInicial, DateTime dataFinal) {

            string address = "order/" + 
                String.Format("{0:yyyy-MM-dd/}", dataInicial) + 
                String.Format("{0:yyyy-MM-dd}", dataFinal);

            XElement ordersXml = APIKanlo.CarregaXml(address);

            XNamespace ad = "http://kanlo.com.br/order";

            return ordersXml.Descendants(ad + "id").Select(o => Int32.Parse(o.Value)).ToList();

        }

        private void SalveContextoOrder() {

            using(OleDbConnection conexao = factoryDAO.GetConexao) {

                OleDbTransaction transacao = null;

                try {

                    conexao.Open();
                    transacao = conexao.BeginTransaction();

                    Ik_orderDAO orderDAO = factoryDAO.Getk_orderDAO(transacao);

                    if(orderDAO.Ache(order.NR_PEDIDO) == null) {

                        IGenericDAO<k_customer> customerDAO = factoryDAO.Getk_customerDAO(transacao);
                        int result = customerDAO.Inclua(order.customer);

                        if(order.customer.phone != null) {
                            IGenericDAO<k_phone> phoneDAO = factoryDAO.Getk_phoneDAO(transacao);
                            phoneDAO.Inclua(order.customer.phone);
                        }

                        if(order.customer.cellphone != null) {
                            IGenericDAO<k_phone> cellphoneDAO = factoryDAO.Getk_cellphoneDAO(transacao);
                            cellphoneDAO.Inclua(order.customer.cellphone);
                        }

                        if(order.AddressBilling != null) {
                            IGenericDAO<k_address> addressbilllingDAO = factoryDAO.Getk_addressbillingDAO(transacao);
                            addressbilllingDAO.Inclua(order.AddressBilling);
                        }

                        if(order.AddressShipping != null) {
                            IGenericDAO<k_address> addressshippingDAO = factoryDAO.Getk_addressshippingDAO(transacao);
                            addressshippingDAO.Inclua(order.AddressShipping);
                        }

                        IGenericDAO<k_payment> paymentDAO = factoryDAO.Getk_paymentDAO(transacao);
                        paymentDAO.Inclua(order.payment);

                        IGenericDAO<k_delivery> deliveryDAO = factoryDAO.Getk_deliveryDAO(transacao);
                        foreach(k_delivery delivery in order.deliveries) {
                            deliveryDAO.Inclua(delivery);
                        }

                        IGenericDAO<k_freight> freightDAO = factoryDAO.Getk_freightDAO(transacao);
                        freightDAO.Inclua(order.cart.freight);

                        IGenericDAO<k_orderLine> orderLineDAO = factoryDAO.Getk_orderLineDAO(transacao);
                        foreach(k_orderLine orderLine in order.cart.orderLines) {
                            orderLineDAO.Inclua(orderLine);
                        }

                        IGenericDAO<k_cart> cartDAO = factoryDAO.Getk_cartDAO(transacao);
                        cartDAO.Inclua(order.cart);

                        orderDAO.Inclua(order);

                    } else {
                        orderDAO.Altere(order);
                    }

                    transacao.Commit();
                } catch {
                    transacao.Rollback();
                    throw;
                }

            }

        }

    }
}
